package com.huo.qq.common;

import java.io.File;
import java.io.FileReader;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.Date;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import com.huo.common.Convert;

/**
 * <p>Description: QQ相关操作(辅助程序)</p>
 * @author Huoyan
 * @version 1.0
 * <p>Copyright 2011</p>
 */

public class QQUtils {
	public final static String SEPARATIVE_SIGN_STRING = " ";//String space
	public final static char SEPARATIVE_SIGN_CHAR = ' ';//Char space
	public final static String SEPARATIVE_ZERO_STRING = " 00 ";
	public final static String SEPARATIVE_SIGN_STRING_WEB = "\\x";
	
	/**
	 * Get the verify code of hex string
	 * @param code
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public static String getVerifyCodeHexString(String code) throws UnsupportedEncodingException{
		return QQUtils.SEPARATIVE_ZERO_STRING + QQUtils.setHexStringSplit(Convert.toHexString(code, false), QQUtils.SEPARATIVE_ZERO_STRING);
	}
	
	/**
	 * Insert spaces in hex string
	 * @param hexstr
	 * @return
	 */
	public static String setHexStringSpace(String hexstr){
		return setHexStringSplit(hexstr, SEPARATIVE_SIGN_STRING);
	}
	
	/**
	 * Insert split string in hex string
	 * @param hexstr
	 * @param split
	 * @return
	 */
	public static String setHexStringSplit(String hexstr, String split){
		StringBuffer newstr = new StringBuffer(delHexStringSpace(hexstr));
		int len = newstr.length();
		int j = 2;
		for (int i = 0; i < len / 2; i++) {
			newstr.insert(j, split);
			j = j + split.length() + 2;
		}
		return newstr.toString();
	}
	
	/**
	 * Delete computer space in hex string 
	 * @param hexstr
	 * @return
	 */
	public static String delHexStringSpace(String hexstr){
		return delHexStringSplit(hexstr, SEPARATIVE_SIGN_STRING);
	}
	
	/**
	 * Delete split string in hex string 
	 * @param hexstr
	 * @param split
	 * @return
	 */
	public static String delHexStringSplit(String hexstr, String split){
		StringBuffer s = new StringBuffer(hexstr);
		for (int i = 0; i < s.length(); i++) {
			//System.out.println(s.toString());
			int n = s.indexOf(split);
			if (n > 0) s.deleteCharAt(n);
			else break;
		}
		return s.toString();
	}
	
	/**
	 * Get random two bytes
	 * @return
	 */
	public static String getRandomTwoBytes() {
		long l = (long) (Math.random() * 100 + 155);
		long l2 = (long) (Math.random() * 100 + 155);
		return Long.toHexString(l) + SEPARATIVE_SIGN_CHAR + Long.toHexString(l2) + SEPARATIVE_SIGN_CHAR;
		//return new StringBuffer().append(Long.toHexString(l)).append(SEPARATIVE_SIGN_STRING)
				//.append(Long.toHexString(l2)).append(SEPARATIVE_SIGN_STRING).toString();
		//return Long.toHexString(l) + SEPARATIVE_SIGN_STRING + Long.toHexString(l2) + SEPARATIVE_SIGN_STRING;
	}
	
	/**
	 * Get message length
	 * @param msg
	 * @return
	 */
	public static String getMessageLength(long msg){
		String s = getHexString(msg);
		return s.substring(s.length()-6, s.length());
	}
	
	/**
	 * Get the current time hex format
	 * @return
	 */
	public static String getNowHexString(){
		long l = 0;
		Date d = null;
		try {
			d = DateFormat.getDateInstance(DateFormat.SHORT).parse("1970-1-1");
		} catch (Exception e) {
			//d = new Date("1970/1/1");
			e.printStackTrace();
		} finally {
			l = (new Date().getTime() - d.getTime()) / 1000 - 8 * 3600;
		}
		return getHexString(l);
	}
	
	/**
	 * The text into 16 hexadecimal space delimited string(Take the 16 hexadecimal QQNumber)
	 * @param s s is a long number for example qqnumber
	 * @return
	 */
	public static String getHexString(long s){
		return getHexString(s, SEPARATIVE_SIGN_STRING);
	}
	
	/**
	 * The text into 16 hexadecimal space delimited string(Take the 16 hexadecimal QQNumber)
	 * @param l l is a long number for example qqnumber
	 * @return
	 */
	public static String getHexString(long l, String splitstr){
		//String nkg = null;
		//byte[] numText7;
		//numText7 = Convert.toByteArray(Convert.toLong(number));
		//nkg = String.format("%02x %02x %02x %02x", numText7[3],numText7[2],numText7[1],numText7[0]);
		StringBuffer sb = new StringBuffer(Long.toHexString(l));
		String c = splitstr;
		if(sb.length() > 8){
			sb.delete(0, sb.length()-8);
		}else{
			for (int i = sb.length(); i < 8; i++) {
				sb.insert(0, '0');
			}
		}
		sb.insert(2, c);
		sb.insert(5, c);
		sb.insert(8, c);
		sb.insert(sb.length(), c);
		return sb.toString();
	}
	
	/**
	 * The text into 16 hexadecimal space delimited string(Take the 16 hexadecimal QQNumber)
	 * @param s s is a long number for example qqnumber
	 * @return
	 */
	public static String getHexString(String s){
		return getHexString(Convert.toLong(s));
	}
	
	/**
	 * call JS to generate the password v2.0
	 * @param p pwd
	 * @param code
	 * @return
	 */
	public static String encodePass(String p, String code) {
		try {
			String path = QQUtils.class.getResource("/").getPath() + "/com/xnet/qqlogin/comm.js";
			ScriptEngineManager m = new ScriptEngineManager();
			FileReader fr = new FileReader(new File(path));
			ScriptEngine se = m.getEngineByName("javascript");
			se.eval(fr);
			Object t = se.eval("md5(md5_3(\"" + p + "\")+\""
					+ code.toUpperCase() + "\");");
			return t.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * QQ number to hex String 
	 * like \x00\x00\x00\x00\x03\x16\x2a\x12
	 * @return hex QQ Number
	 */
	public static String uin2hex(String qq) {
		int maxLength = 16;
		long q = Long.parseLong(qq);
		StringBuffer hexqq = new StringBuffer(getHexString(q, ""));
		//补0
		for (int i = 0; i < maxLength; i += 2) {
			hexqq.insert(0, "0");
		}
		//加\x
		for (int i = 0; i < maxLength*2; i += 4) {
			hexqq.insert(i, "\\x");
		}
		return hexqq.toString();
	}
	
	/**
	 * call JS to generate the password v3.0
	 * @param password
	 * @param vcode
	 * @param uin  The Hex QQNumber
	 * @return
	 */
	public static String encodePass(String password, String vcode, String uin) {
		String[] us = uin.split("\\\\x");
		byte[] uinByte = new byte[us.length - 1];
		if (us.length == 9) {
			for (int i = 1; i < us.length; i++) {
				uinByte[i - 1] = getByte(Integer.parseInt(us[i], 16));
			}
		}
		return md5(md5(getByte(hexchar2bin(md5(password)), uinByte))
				+ vcode.toUpperCase());
	}
	
	public static String md5(byte[] source) {
		String s = null;
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			java.security.MessageDigest md = java.security.MessageDigest
					.getInstance("MD5");
			md.update(source);
			byte tmp[] = md.digest();
			char str[] = new char[16 * 2];
			int k = 0;
			for (int i = 0; i < 16; i++) {
				byte byte0 = tmp[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			s = new String(str);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return s.toUpperCase();
	}

	public static String md5(String str) {
		return md5(str.getBytes()).toUpperCase();
	}

	public static byte[] hexchar2bin(String str) {
		byte[] bytes = new byte[str.length() / 2];
		int j = 0;
		for (int i = 0; i < str.length(); i = i + 2) {
			int iv = Integer.parseInt(str.substring(i, i + 2), 16);
			bytes[j++] = getByte(iv);
		}
		return bytes;
	}

	public static byte getByte(int intValue) {
		int byteValue = 0;
		int temp = intValue % 256;
		if (intValue < 0) {
			byteValue = temp < -128 ? 256 + temp : temp;
		} else {
			byteValue = temp > 127 ? temp - 256 : temp;
		}
		return (byte) byteValue;
	}

	public static byte[] getByte(byte[] b1, byte[] b2) {
		byte[] bs = new byte[b1.length + b2.length];
		int i = 0;
		for (i = 0; i < b1.length; i++) {
			bs[i] = b1[i];
		}
		for (int j = 0; j < b2.length; j++) {
			bs[i + j] = b2[j];
		}
		return bs;
	}//encrypt.End
	
	/**
	 * Get param of r
	 * @return
	 */
	public static double getRandom(){
		return Math.random();
	}
	
	/**
	 * According to nanosecond time to generate the client ID
	 * @return
	 */
	public static long createClientID(){
		return (long)(System.nanoTime()+Math.random());
	}
	public static void test(){
		long a=System.currentTimeMillis();
		for(int i=0;i<10000;i++)
			uin2hex("51784370");
		System.out.println(System.currentTimeMillis()-a);
	}
	
	public static void main(String[] args) {
		test();
		System.out.println(uin2hex("51784370"));
	}
}
